﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using JXT.PrimaryKey.Batman.Core.Configuration;
using JXT.PrimaryKey.Batman.Core.Infrastructure;

namespace JXT.PrimaryKey.Batman.Domain.Repositories.SqlServer
{
    /// <summary>
    /// SqlServer数据库存储上下文对象
    /// </summary>
    public class SqlServerRepositoryContext : RepositoryContext
    {
        /// <summary>
        /// 数据库连接字符串
        /// </summary>
        public string ConnectionString { get; private set; }

        /// <summary>
        /// 数据库连接对象
        /// </summary>
        public DbConnection Connection
        {
            get
            {
                if (ObjectContext is DbConnection && (ObjectContext as DbConnection).State == ConnectionState.Closed)
                {
                    (ObjectContext as DbConnection).Open();
                }
                return ObjectContext as DbConnection;
            }
            private set { ObjectContext = value; }
        }

        //private Stack<DbTransaction> _transactionStack = new Stack<DbTransaction>();
        private DbTransaction _transaction;
        private uint _transactionCount = 0;

        /// <summary>
        /// 构造方法
        /// </summary>
        /// <param name="connectionName">数据库连接名称</param>
        public SqlServerRepositoryContext(string connectionName)
        {
            //string connectionName = "default";
            ConfigurationName = connectionName;
            var configurationSection = SupernovaConfigurationManager.GetServiceConfigurationSection();
            if (configurationSection != null)
            {
                if (String.IsNullOrEmpty(connectionName) || connectionName.Equals("default", StringComparison.InvariantCultureIgnoreCase))
                {
                    ConnectionString = configurationSection.ConnectionSetting.DefaultConnectionString;
                }
                else
                {
                    var connectionSetting = configurationSection.ConnectionSetting[connectionName];
                    if (connectionSetting == null)
                        ConnectionString = configurationSection.ConnectionSetting.DefaultConnectionString;
                    else
                        ConnectionString = connectionSetting.ConnectionString;
                }
            }
            Connection = new SqlConnection(ConnectionString);
        }

        public override void BeginTransaction()
        {
            if (_transaction == null)
            {
                _transaction = Connection.BeginTransaction();
                _transactionCount = 1;
            }
            else
            {
                _transactionCount++;
            }
        }

        public override void CommitTransaction()
        {
            _transactionCount--;
            if (_transactionCount <= 0 && _transaction != null)
            {
                _transaction.Commit();
            }
        }

        public override void RollbackTransaction()
        {
            _transactionCount--;
            if (_transactionCount <= 0 && _transaction != null)
            {
                _transaction.Rollback();
            }
        }

        public override void DisposeTransaction()
        {
            if (_transactionCount <= 0 && _transaction != null)
            {
                _transaction.Dispose();
                _transaction = null;
            }
        }

        /// <summary>
        /// 创建Command对象，并在适当的时候提供Transaction对象
        /// </summary>
        /// <returns></returns>
        public DbCommand CreateCommand()
        {
            var command = Connection.CreateCommand();
            if (_transaction != null)
                command.Transaction = _transaction;
            return command;
        }

        public override void Dispose()
        {
            base.Dispose();
            var connection = ObjectContext as DbConnection;
            if (connection != null && connection.State != ConnectionState.Closed)
            {
                connection.Dispose();
                ObjectContext = null;
            }
        }
    }
}
